Eureka: Service Discovery Clients
👉 Complete tutorial on registering microservices with Eureka Name server.
👉 Complying with best practices and security recommendations.
Microservice as Eureka clients
A Eureka Client is any microservice that registers itself with the Eureka Naming Server to become discoverable by other services.
By registering, the service provides it’s metadata (name, IP, port) and maintains a “heartbeat” to signal that it is alive and ready to handle traffic.
To enable discovery in a Spring Boot service, we need to include the client-side discovery dependency.
Maven dependency
Add the following starter to your microservice’s pom.xml. It adds the capability for both, Registration (acting as an instance) and Discovery (acting as a client to find others).
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Enabling service discovery
To activate the discovery client, you annotate your main application class. While modern Spring Cloud versions (since 1.4+) often enable this automatically if the JAR is on the classpath, using the annotation is a best practice for clarity.
Use @EnableDiscoveryClient or @EnableEurekaClient.
@SpringBootApplication
@EnableDiscoveryClient
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
Insight:
→ Use@EnableDiscoveryClientfor Generic annotation / Vendor neutrality.
→ Use@EnableEurekaClientonly if you want to strictly bind your code to Netflix Eureka.
| @EnableEurekaClient | @EnableDiscoveryClient |
|---|---|
| Enables service registration and discovery only with Eureka. | More generic, works with multiple service registries. |
| It supports only Netflix Eureka. | It supports Eureka, Consul, Zookeeper, etc. |
| It’s a concrete implementation. | It’s an interface or contract. |
| It needs the spring-cloud-starter-netflix-eureka-client dependency to work. | It’s a part of Spring Cloud dependencies. No specific dependency is needed. |
Client configuration
The client needs to know the location of the Naming Server. This is defined in the application config file - application.yml or application.properties.
spring:
application:
name: product-service # Mandatory, This becomes the Service ID in Eureka
server:
port: 8081
eureka:
client:
service-url:
defaultZone: http://eureka-host:8761/eureka/ # Eureka Server
instance:
prefer-ip-address: true # Recommended for Docker/Cloud environments
Insight:
→eureka.instance.prefer-ip-address: If set totrue, Eureka registers the IP of the service, instead of the hostname (more reliable in virtual networks eg. K8s).
Request flow
sequenceDiagram
participant B as Microservice B (Provider)
participant E as Eureka Server
participant A as Microservice A (Consumer)
Note over B,E: 1. Registration Phase
B->>E: POST /eureka/apps/SERVICE-B (IP, Port, Metadata)
E-->>B: 204 No Content (Registered)
Note over B,E: 2. Health Monitoring
loop Every 30 Seconds
B->>E: PUT /eureka/apps/SERVICE-B (Heartbeat)
E-->>B: 200 OK
end
Note over A,E: 3. Discovery Phase
A->>E: GET /eureka/apps (Fetch Registry)
E-->>A: 200 OK (JSON/XML List of all Services)
Note right of A: A caches registry locally
Note over A,B: 4. Service Consumption
A->>A: Client-side Load Balance (Select Instance of B)
A->>B: GET /api/data (Direct Call)
B-->>A: 200 OK (Response)
Note over E,B: 5. Eviction (If Heartbeat Fails)
Note right of E: After 90s of no heartbeats...
E->>E: Remove B from Registry
Health checks & Actuator
By default, Eureka determines a service’s status via a simple Heartbeat (is the application process running?). This can be misleading; as a service might be “alive” but could be “broken”, if its database or message broker is down.
By enabling Actuator Health checks, Eureka shifts from a passive heartbeat to an active health probe. It will only mark a service as UP if all internal health indicators (database, disk space, custom checks) are also GREEN.
To implement this, include the Actuator dependency and enable the Eureka health check bridge.
Maven dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Application configuration
eureka:
client:
healthcheck:
enabled: true # Propagates Actuator status to Eureka
management:
endpoints:
web:
exposure:
include: "health" # Ensures the /health endpoint is available
endpoint:
health:
show-details: always # Optional: useful for debugging
Heartbeat vs. Health check
| Feature | Default Heartbeat | Actuator Health Check |
|---|---|---|
| Detection Level | Process/Network level. | Application/Dependency level. |
| Logic | I am still standing. | I am ready to process traffic. |
| Failure Scenario | Only marks DOWN if the app crashes. | Marks OUT_OF_SERVICE if internal dependent services status eg. Database, Message Broker etc. is unhealthy. |
| Best For | Development / Simple apps. | Production / Mission-critical apps. |
Note:
→ When health checks are enabled, if a service’s database goes down, its status in the Eureka dashboard will change fromUPtoOUT_OF_SERVICE.
→ This automatically stops Ribbon or LoadBalancer from routing traffic to that specific instance.
Best Practices for Credentials
In PROD grade applications, credentials are never hardcode. We use one of the following strategies to inject credentials safely.
→ Environment Variables
Inject the username and password from your CI/CD pipeline or container orchestrator (like Kubernetes Secrets).
eureka:
client:
service-url:
defaultZone: http://${EUREKA_USER}:${EUREKA_PASSWORD}@eureka-server:8761/eureka/
→ Spring Cloud Vault / Config Server
When using HashiCorp Vault, Spring can fetch the credentials at startup and resolve the placeholders dynamically. This allows for secret rotation without redeploying code.
→ Placeholder Resolution
We can separate the credentials from the URL structure to make the config more readable:
eureka:
client:
service-url:
defaultZone: http://admin:${eureka.password}@eureka-server:8761/eureka/
Security hardening checklist
| Practice | Why it’s necessary |
|---|---|
| Always Use HTTPS | Basic Auth sends credentials as Base64 encoded strings; without SSL/TLS, they are easily intercepted. |
| Disable CSRF | Eureka clients send POST and PUT requests. Disable CSRF for the /eureka/** path on the server. |
| Network Isolation | Keep the Eureka server on an internal VPC or private subnet. It should never be accessible from the public internet. |
| Separate Admin Users | Use different credentials for the Dashboard (human users) and the Service Registry (automated clients). |
| IP Whitelisting | If possible, restrict access to the Eureka server to specific IP ranges (e.g., your Kubernetes pod CIDR). |
Security Levels summary
| Method | Security Level | Complexity | Best For… |
|---|---|---|---|
| No Auth | 🔴 Low | None | Local development only. |
| Basic Auth | 🟡 Medium | Low | Small-to-medium clusters via HTTPS. |
| Basic + Vault | 🟢 High | Medium | Enterprise apps needing secret rotation. |
| mTLS (Certs) | 🟣 Maximum | High | High-security environments (Finance/Gov). |
Self-Registration Lifecycle
| Phase | Description | Default Interval |
|---|---|---|
| Registration | On startup, the client sends a POST request with its metadata. | Once on app boot |
| Heartbeat | The client sends a PUT request to renew its lease | Every 30 seconds (default) |
| Fetch Registry | The client downloads the local cache of other services so it can call them even if Eureka goes down momentarily. | Every 30 seconds |